package itsm.isperp.framework.utils;

import itsm.isperp.framework.collection.tree.ITreeNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 树形节点的辅助工具
 * 
 * @author lizx
 * @date 2013-2-5
 * @version V1.0
 */
public final class TreeNodeUtils {

	/**
	 * 将一个树节点的列表转换为具有树形结构的列表。
	 * 
	 * 使用方法： <br />
	 * {@code 
	 * List<BaseNode> menus = new ArrayList<BaseTreeNode>();
	 * //构建列表createMenu(id,name,parentId);
	 * menus.add(createMenu("1", "1", ""));
	 * menus.add(createMenu("2", "2", ""));
	 * 
	 * menus.add(createMenu("3", "1.3", "1"));
	 * menus.add(createMenu("4", "1.4", "1"));
	 * menus.add(createMenu("5", "1.5", "1"));
	 * 
	 * menus.add(createMenu("6", "2.6", "6"));
	 * 
	 * menus.add(createMenu("7", "1.4.7", "4"));
	 * menus.add(createMenu("8", "1.4.7.8", "7"));
	 *  //格式化为一个树形列表
	 * 	List<ITreeNode> nodes = TreeNodeUtils.parseFormList(menus);
	 *  //序列化
	 * 	String json = JsonBuilder.buildNormalBinder().toJson(nodes);
	 *  //输出结果
	 * 	System.out.println(json);
	 *  
	 *   结果：
	 *  [ "id":"1","name":"1","parentId":"","children":[ "id":"3","name":"1.3","parentId":"1","children":null,"text":"1.3"}
	 * , {"id":"4","name":"1.4" ,"parentId":"1","children":[{"id"
	 * :"7","name":"1.4.7"... ...},{ "id": "2","name":"2","parentId":""}]
	 * 
	 * }
	 * 
	 * @param list
	 *            列表
	 * @return 树形结构列表
	 */
	public static final <S extends ITreeNode> List<S> parseFormList(List<S> list) {
		return bulidFormList(list);
	}

	/**
	 * 与{@link TreeNodeUtils#parseFormList(List)}一致，并同时为此树形列表增加一个根节点。
	 * 
	 * 
	 * @param list
	 *            列表
	 * @return 树形结构列表
	 */
	public static final <S extends ITreeNode> List<S> parseAndAddRootFormList(
			Class<S> clazz, List<S> list, boolean showRoot) {

		List<S> nodeList = bulidFormList(list);

		if (showRoot) {
			List<S> result = new ArrayList<S>();
			S root = creatRootTreenode(clazz);
			root.setChildren(nodeList);
			result.add(root);
			return result;
		} else {

			return nodeList;
		}

	}

	/**
	 * 将一个树节点的列表转换为具有树形结构的列表。
	 * 
	 * @param list
	 *            列表
	 * @return 树形结构列表
	 */
	private static final <S extends ITreeNode> List<S> bulidFormList(
			List<S> list) {

		List<S> nodeList = new ArrayList<S>();

		if (list == null)
			return nodeList;

		for (S node1 : list) {
			boolean mark = false;

			// if (org.apache.commons.lang3.StringUtils.isEmpty(node1
			// .getParentId())) {
			//
			// }

			for (S node2 : list) {
				// count++;
				if (node1.getParentId() != null
						&& node1.getParentId().equals(node2.getId())) {
					mark = true;
					if (node2.getChildren() == null)
						node2.setChildren(new ArrayList<S>());
					((List<S>) node2.getChildren()).add(node1);
					break;
				}
			}
			if (!mark) {
				nodeList.add(node1);
			}
		}

		return nodeList;

	}

	public static <S extends ITreeNode> S creatRootTreenode(Class<S> clazz) {
		return creatRootTreenode(clazz, "所有");
	}

	/**
	 * 创建一个属性根节点
	 * 
	 * @return 属性根节点
	 */
	public static <S extends ITreeNode> S creatRootTreenode(Class<S> clazz,
			String rootName) {
		S root = null;
		try {
			root = clazz.newInstance();
		} catch (Exception e) {
			return root;
		}
		root.setId("");
		root.setName(rootName);
		root.setTreenodePath("/");
		root.setTreenodeNamePath("/");
		root.setOpen(true);

		return root;
	}

	public String getUpdatePath(String oldPath, String newPath) {
		if (oldPath == null || oldPath.trim().length() < 1
				|| oldPath.trim().equals(ITreeNode.DEFAULT_PATH_SEPARATOR)) {
			return "";
		}

		if (newPath == null || newPath.trim().length() < 1) {
			newPath = ITreeNode.DEFAULT_PATH_SEPARATOR.toString();
		}
		if (oldPath.charAt(0) != '-') {
			oldPath = ITreeNode.DEFAULT_PATH_SEPARATOR + oldPath;
		}
		if (oldPath.charAt(oldPath.length() - 1) != '-') {
			oldPath = oldPath + ITreeNode.DEFAULT_PATH_SEPARATOR;
		}
		if (newPath.charAt(0) != '-') {
			newPath = ITreeNode.DEFAULT_PATH_SEPARATOR + newPath;
		}
		if (newPath.charAt(newPath.length() - 1) != '-') {
			newPath = newPath + ITreeNode.DEFAULT_PATH_SEPARATOR;
		}

		final String newPathTemp = newPath.trim();
		final String oldPathTemp = oldPath.trim();

		StringBuilder hql = new StringBuilder();
		hql.append(" update ");
		hql.append(" table");
		hql.append(" o ");
		hql.append(" set o.treenode_path=replace(treenode_path,"
				+ oldPathTemp.trim());
		hql.append(",").append(newPathTemp).append(")");

		hql.append(" set o.treenodename_path=replace(treenodename_path,"
				+ oldPathTemp.trim());
		hql.append(",").append(newPathTemp).append(")");

		hql.append(" where o.treenode_path  like %" + oldPathTemp + "%");

		return hql.toString();

	}

	public static int rebulidTree(String tableName) {

		// CallableStatement statBuildTree = con
		// .prepareCall("{CALL sp_treenode_rebuild(?)}");
		// statBuildTree.setString(1, tableName);
		// return statBuildTree.executeUpdate();

		return 0;
	}

	/**
	 * 重新排序树
	 * 
	 * @param list
	 * @return
	 */
	public static final List<Map<String, Object>> sortTree(
			List<Map<String, Object>> list) {
		List<Map<String, Object>> nodeList = buildTree(list);
		List<Map<String, Object>> nodeList2 = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> node1 : nodeList) {
			addTreeList(node1, nodeList2);
		}

		return nodeList2;

	}

	private static final void addTreeList(Map<String, Object> node,
			List<Map<String, Object>> list) {
		List<Map<String, Object>> children = ((List<Map<String, Object>>) node
				.get("children"));

		list.add(node);
		// node.remove("children");

		if (children != null && children.size() != 0) {
			for (Map<String, Object> m : children) {
				addTreeList(m, list);
			}
		}

	}

	private static final List<Map<String, Object>> buildTree(
			List<Map<String, Object>> list) {
		List<Map<String, Object>> nodeList = new ArrayList<>();

		for (Map<String, Object> node1 : list) {
			boolean mark = false;
			String parentId = (String) node1.get("parent_id");
			for (Map<String, Object> node2 : list) {
				String id = (String) node2.get("id");

				if (parentId != null && parentId.equals(id)) {
					mark = true;
					if (node2.get("children") == null)
						node2.put("children",
								new ArrayList<Map<String, Object>>());
					((List<Map<String, Object>>) node2.get("children"))
							.add(node1);
					break;
				}
			}
			if (!mark) {
				nodeList.add(node1);
			}
		}
		return nodeList;

	}

}
